package com.bdqn.crm.config.shiro;

import com.alibaba.druid.sql.visitor.functions.Right;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bdqn.crm.pojo.SysRight;
import com.bdqn.crm.pojo.SysRole;
import com.bdqn.crm.pojo.SysUser;
import com.bdqn.crm.service.SysUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 安全数据源
 */
public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    private SysUserService sysUserService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    //redis 中数据的 key 的前缀
    private String SHIRO_LOGIN_COUNT = "shiro_login_count";  //登录计数
    private String SHIRO_IS_LOCK = "shiro_is_lock"; //锁定用户登录

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("调用 MyShiroRealm.doGetAuthorizationInfo 获取权限信息！");
        //获得权限信息
        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //静态授权：授予主体(用户)相应的角色和权限
//        info.addRole(sysUser.getRole().getRoleName());
//        info.addStringPermission("用户列表");  //所有用户用于用户列表的权限
//        if("管理员".equals(sysUser.getRole().getRoleName())){  //管理员拥有增删改的权限
//            info.addStringPermission("用户添加");
//            info.addStringPermission("用户编辑");
//            info.addStringPermission("用户删除");
//        }
        //动态授权
        SysRole sysRole = sysUser.getRole();
        System.out.println(sysRole.toString());
        if (sysRole !=null){
            info.addRole(sysUser.getRole().getRoleName());
            Set<SysRight> rights = sysRole.getRights();
            if(rights !=null && rights.size()>0){
                for (SysRight right : rights){
                    info.addStringPermission(right.getRightCode());
                }
            }
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("调用 MyShiroRealm.doGetAuthenticationInfo 获取身份信息！");
        //获取身份信息
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String usrName = token.getUsername();

        //每次访问次数加1
        ValueOperations<String,String> operations = stringRedisTemplate.opsForValue();
        operations.increment(SHIRO_LOGIN_COUNT+usrName,1);
        //计数大于5时，设置用户被锁定一小时，清空登记计数
        if (Integer.parseInt(operations.get(SHIRO_LOGIN_COUNT+usrName))>5){
            operations.set(SHIRO_IS_LOCK+usrName,"LOCK");
            stringRedisTemplate.expire(SHIRO_LOGIN_COUNT+usrName,1, TimeUnit.HOURS);
            stringRedisTemplate.delete(SHIRO_LOGIN_COUNT+usrName); //清空登录计数
        }
        if ("LOCK".equals(operations.get(SHIRO_IS_LOCK+usrName))){
            throw new DisabledAccountException();
        }
        SysUser sysUser = sysUserService.getlogin(usrName);
        if(sysUser == null){
            throw new UnknownAccountException();  //账号错误
        }
        if (sysUser.getUsrFlag() == null || sysUser.getUsrFlag().intValue() == 0){
            throw new LockedAccountException();  //账号锁定
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                sysUser,//身份(根据用户名查询数据库获得的用户)
                sysUser.getUsrPassword(),//凭证（查询数据库获得的密码）
                ByteSource.Util.bytes("czkt"),
                getName()//Realm对象名称
        );
        return info;
    }
}
